﻿using IM.Easy.AuthorizationServices.IServices;
using IM.Easy.Core.OAuth;
using IM.Easy.Core.OAuth.OAuthUser;
using IM.Easy.Core.OAuth.Providers;
using IM.Easy.Core.ServiceLifetime;
using IM.Easy.CoreServices.IServices;
using IM.Easy.CoreServices.Services;
using IM.Easy.Entity.System;
using IM.Easy.Infrastructure.Constants;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Policy;
using System.Text;
using System.Threading.Tasks;
using System.Web;

namespace IM.Easy.AuthorizationServices.Services
{
    public class AuthorizationService : IAuthorizationService, ITransient
    {
        private readonly OAuthProviderFactory _oAuthProviderFactory;
        private readonly IParamsService _paramsService;
        private readonly IAuthConfigService _authConfigService;
        public string AccessToken { get; private set; }


        public AuthorizationService(OAuthProviderFactory oAuthProviderFactory, IParamsService paramsService, IAuthConfigService authConfigService)
        {
            _oAuthProviderFactory = oAuthProviderFactory;
            _paramsService = paramsService;
            _authConfigService = authConfigService;
        }

        /// <summary>
        /// 获取授权地址
        /// </summary>
        /// <param name="provider">提供商</param>
        /// <param name="queryParams">回调参数</param>
        /// <returns></returns>
        public string GetAuthUrl(string provider, Dictionary<string, string> queryParams)
        {
            var callbackUri = GetCallbackUrl(queryParams);
            var authProvider = _oAuthProviderFactory.Create(provider);
            var authUrl = authProvider.GetAuthorizationUrl(callbackUri);
            return authUrl;
        }

        /// <summary>
        /// 获取授权地址
        /// </summary>
        /// <param name="provider">提供商</param>
        /// <param name="redirectUrl">回调地址</param>
        /// <returns></returns>
        public string GetAuthUrl(string provider, string redirectUrl)
        {
            var authconfig = _authConfigService.Get(provider);
            var callbackUri = GetCallbackUrl(redirectUrl);
            var authProvider = _oAuthProviderFactory.Create(provider, new AuthOptions { ClientId = authconfig.ClientId, ClientSecret = authconfig.ClientSecret });
            var authUrl = authProvider.GetAuthorizationUrl(callbackUri);
            return authUrl;
        }

        /// <summary>
        /// 处理认证过程，使用提供的认证码（code）和认证提供商（provider）
        /// </summary>
        /// <param name="code">认证提供商返回的认证码，通常在授权回调时提供。</param>
        /// <param name="provider">认证提供商的名称，例如 Google、Facebook、GitHub 等。</param>
        /// <param name="queryParams">附加的查询参数，通常用于携带其他必要的信息，如重定向 URL。</param>
        /// <returns>返回包含用户信息的对象（UserInfo），如果认证成功。</returns>
        /// <exception cref="UnauthorizedAccessException">如果认证失败，抛出未经授权的异常。</exception>
        public async Task<UserInfo> AuthenticateUserAsync(string code, string provider, Dictionary<string, string> queryParams)
        {
            // 认证逻辑
            var callbackUri = GetCallbackUrl(queryParams);
            var authProvider = _oAuthProviderFactory.Create(provider);
            var token = await authProvider.GetAccessTokenAsync(code, callbackUri);

            var userInfo = await authProvider.GetUserInfoAsync(token.AccessToken);
            userInfo.Provider = provider;
            return userInfo;
        }

        /// <summary>
        /// 处理认证过程，使用提供的认证码（code）和认证提供商（provider）
        /// </summary>
        /// <param name="code">认证提供商返回的认证码，通常在授权回调时提供。</param>
        /// <param name="provider">认证提供商的名称，例如 Google、Facebook、GitHub 等。</param>
        /// <param name="queryParams">附加的查询参数，通常用于携带其他必要的信息，如重定向 URL。</param>
        /// <returns>返回包含用户信息的对象（UserInfo），如果认证成功。</returns>
        /// <exception cref="UnauthorizedAccessException">如果认证失败，抛出未经授权的异常。</exception>
        public async Task<UserInfo> AuthenticateUserAsync(string code, string provider, string redirectUrl)
        {
            var authconfig = _authConfigService.Get(provider);
            var callbackUri = GetCallbackUrl(redirectUrl);
            var authProvider = _oAuthProviderFactory.Create(provider, new AuthOptions { ClientId = authconfig.ClientId, ClientSecret = authconfig.ClientSecret });
            var token = await authProvider.GetAccessTokenAsync(code, callbackUri);
            AccessToken = token.AccessToken;
            var userInfo = await authProvider.GetUserInfoAsync(token.AccessToken);
            userInfo.Provider = provider;
            return userInfo;
        }

        private string GetCallbackUrl(Dictionary<string, string> queryParams)
        {
            var websiteHost = _paramsService.GetValue(ParamsConstant.WebsiteHost, true);
            // 构造回调地址
            var callbackUri = new UriBuilder(websiteHost)
            {
                Path = "/oauth/callback",
                Port = -1,   //防止生成默认的80端口
                Query = BuildQueryString(queryParams)
            }.ToString();
            return callbackUri;
        }

        private string GetCallbackUrl(string redirectUrl)
        {
            var websiteHost = _paramsService.GetValue(ParamsConstant.WebsiteHost, true);
            var uri = new Uri(websiteHost);

            // 判断是否包含查询参数
            var parts = redirectUrl.Split('?', 2); // 仅分割一次
            var path = parts[0]; // 路径部分
            var query = parts.Length > 1 ? parts[1] : string.Empty; // 查询部分，如果没有则为空

            var callbackUri = new UriBuilder(uri)
            {
                Path = path,
                Query = string.IsNullOrEmpty(query) ? null : query, // 如果没有查询参数，设置为 null
                //Port = -1 ,// 防止生成默认的80端口
                Port = uri.Port
            }.ToString();
            return callbackUri;
        }


        private string BuildQueryString(Dictionary<string, string> queryParams)
        {
            return string.Join("&", queryParams.Select(kvp => $"{kvp.Key}={Uri.EscapeDataString(kvp.Value)}"));
        }


    }
}
